package com.block.datapush.form.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.datapush.form.service.IDataPushFormService;
import com.block.datapush.form.service.IFormInfoPushRecordService;
import com.block.datapush.form.service.IFormInfoService;
import com.block.db.entity.FormInfo;
import com.block.db.entity.FormInfoPushRecord;
import com.block.db.entity.MemberExtInfo;
import com.block.db.mapper.FormInfoPushRecordMapper;
import com.block.db.mapper.MemberExtInfoMapper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * api手动推送记录 服务实现类
 * </p>
 *
 * @author 
 * @since 2023-02-27
 */
@Service
public class FormInfoPushRecordServiceImpl extends ServiceImpl<FormInfoPushRecordMapper, FormInfoPushRecord> implements IFormInfoPushRecordService {

    @Autowired
    IFormInfoService formInfoService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    IDataPushFormService dataPushFormService;
    @Resource
    MemberExtInfoMapper memberExtInfoMapper;

    private static String PUSH_RECORD_DATA_HASH_KEY = "PUSH:RECORD:DATA:HASH:KEY:";

    /**
     * 查询未执行的推送任务，并执行
     *
     */
    @Override
    public void queryExecutePushRecord(JSONArray recordIds) {

        for (int index = 0; index< recordIds.size(); index++) {
            String recordId = recordIds.getString(index);
            try {
                ((IFormInfoPushRecordService)AopContext.currentProxy()).executeSinglePushRecord(recordId);
            }catch (Exception exception){
                exception.printStackTrace();
            }
        }
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public void executeSinglePushRecord(String recordId) throws Exception {

        FormInfoPushRecord pushRecord =  this.baseMapper.getEntityByIdLock(recordId);
        if (ObjectUtil.isEmpty(pushRecord)){
            return;
        }

        String redisKey = PUSH_RECORD_DATA_HASH_KEY + pushRecord.getId();
        if (StrUtil.equals(String.valueOf(pushRecord.getStatus()), "0")){
            // 启用执行
            List<MemberExtInfo> extInfoList = memberExtInfoMapper.getExtInfoByTime(pushRecord.getStarttime(), pushRecord.getEndtime());

            List<String> zhimaFilterList = new ArrayList<>();
            if (StrUtil.isNotEmpty(pushRecord.getFilterZhima())){
                zhimaFilterList = JSON.parseArray(pushRecord.getFilterZhima(), String.class);
            }

            List<Long> uidList = new ArrayList<>();
            for (MemberExtInfo memberExtInfo : extInfoList) {
                if (CollUtil.isEmpty(zhimaFilterList)){
                    // 过滤条件为空
                    uidList.add(memberExtInfo.getUid());
                }else{
                    // 过滤条件不为空
                    if (zhimaFilterList.contains(memberExtInfo.getZhimaScore())){
                        uidList.add(memberExtInfo.getUid());
                    }
                }
            }

            redisTemplate.opsForSet().add(redisKey, uidList.toArray());

            FormInfoPushRecord updateEntiy = new FormInfoPushRecord();
            updateEntiy.setId(pushRecord.getId());
            updateEntiy.setStatus(1);
            updateEntiy.setTotalNumber(uidList.size());
            updateEntiy.setRunStartTime(LocalDateTime.now());
            boolean update = this.updateById(updateEntiy);
            if (!update){
                return;
            }
        }

        // 开启循环执行，知道执行到一个成功的才结束
        while (true){

            Long uid = (Long) redisTemplate.opsForSet().pop(redisKey);
            if (ObjectUtil.isEmpty(uid)){
                // 数据跑完了，任务执行结束
                // 更新任务状态
                redisTemplate.delete(redisKey);

                FormInfoPushRecord updateEntiy = new FormInfoPushRecord();
                updateEntiy.setId(pushRecord.getId());
                updateEntiy.setStatus(2);
                updateEntiy.setRunEndTime(LocalDateTime.now());
                updateEntiy.setDescInfo("数据执行结束");
                boolean update = this.updateById(updateEntiy);
                break;
            }

            MemberExtInfo memberExtInfo = memberExtInfoMapper.selectById(uid);
            FormInfo formInfo = formInfoService.getById(pushRecord.getDataId());
            // 进行数据的推送

            boolean b = dataPushFormService.toPushData(formInfo, memberExtInfo, "MANUAL");

            boolean update = this.baseMapper.updateExecResultByRecordId(pushRecord.getId(), b, LocalDateTime.now());

            if (b){
                break;
            }

        }
    }

}
